package com.guardchina.framework.util.utils;

import com.guardchina.framework.util.constant.ResultStatus;
import com.guardchina.framework.util.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Optional;

/**
 * 描述：文件工具类
 *
 * @author lwb
 * @date 2019/3/23 14:17
 */
@Slf4j
public class FileUtil {

    public static String FILE_NAME_SEPARATOR = ".";
    private static final int BUF_SIZE = 2 * 1024;
    /**
     * 水印缩放大小
     */
    private static final double WATERMARK_RATIO = (double) 1/10;
    /**
     * x轴水印个数
     */
    private static final int X_WATERMARK_NUM = 2;
    /**
     * y轴水印个数
     */
    private static final int Y_WATERMARK_NUM = 2;

    /**
     * 获取文件后缀 example input text.txt return txt
     * @param fileName 文件名
     * @return 文件后缀
     */
    public static String getFileExtension(String fileName){

        
        return Optional.ofNullable(fileName).map(name -> {
            if(name.indexOf(FILE_NAME_SEPARATOR) <= 0){
                throw new BusinessException(ResultStatus.BUSINESS_ERROR, "文件名不合法", String.format("fileName[%s]", fileName));
            }
            return name.substring(name.lastIndexOf(FILE_NAME_SEPARATOR) + 1);
        }).orElseThrow(()->
                new BusinessException(ResultStatus.BUSINESS_ERROR, "文件名不能为空"));
    }

    /**
     * 去掉文件名的后缀 example text.txt -> test  text -> text
     * @param fileName 文件名
     * @return 去掉后缀的文件名
     */
    public static String getFileNameWithoutExtension(String fileName){
        return Optional.ofNullable(fileName).map(name -> {
            if(name.indexOf(FILE_NAME_SEPARATOR) <= 0){
                return name;
            }
            return name.substring(0, name.indexOf(FILE_NAME_SEPARATOR));
        }).orElseThrow(()->
                new BusinessException(ResultStatus.BUSINESS_ERROR, "文件名不能为空"));
    }

    /**
     * 保存文件
     * @param input 文件输入流
     * @param filePath 文件路径
     * @param fileName 文件名
     * @return 文件
     */
    public static File saveFile(InputStream input, String filePath, String fileName){
        File tempFile = new File(filePath + File.separator + fileName);

        copyInputStreamToFile(input, tempFile);

        return tempFile;
    }

    /**
     * 根据文件模糊过滤文件
     * @param dir 文件目录
     * @param fileName 文件名
     * @return 文件数组
     */
    public static File[] filterFileByName(File dir, String fileName){
        if(dir == null || !dir.exists()){
            throw new BusinessException("文件目录不存在");
        }

        if(StringUtils.isBlank(fileName)){
            throw new BusinessException("文件名不存在");
        }

        return dir.listFiles((directory, name) -> name.contains(fileName));
    }

    /**
     * 合并文件
     * @param targetFile 合并的文件
     * @param files 需要合并的文件
     */
    public static void mergeFile(File targetFile, List<File> files){
        BufferedOutputStream outputStream = null;
        BufferedInputStream inputStream = null;
        try {
            outputStream = new BufferedOutputStream(new FileOutputStream(targetFile, true));
            byte[] buffer = new byte[1024];
            for (File file : files) {
                log.debug("合并文件：{}", file.getName());
                inputStream = new BufferedInputStream(new FileInputStream(file));
                int readCount;
                while ((readCount = inputStream.read(buffer)) > 0) {
                    outputStream.write(buffer, 0, readCount);
                }
            }

        } catch (Exception e) {
            throw new BusinessException("文件合并出错" , String.format("targetFile[%s]", targetFile.getPath()),  e);
        }finally {
            try {
                if(outputStream != null){
                    outputStream.flush();
                    outputStream.close();
                }

                if(inputStream != null){
                    inputStream.close();
                }
            }catch (Exception e){
                log.error("关闭文件流失败", e);
            }
        }

        log.debug("合并合并完成：{}", targetFile.getName());

    }

    /**
     * 批量删除文件
     * @param files 文件列表
     */
    public static void deleteFiles(List<File> files){
        if(CollectionUtils.isEmpty(files)){
            return;
        }

        for (File file : files){
            if(!file.delete()){
                log.error("删除文件失败：{}", file.getPath());
            }
        }
    }


    public static void copyInputStreamToFile(InputStream inputStream, File file){
        OutputStream out = null;

        try {

            out = new BufferedOutputStream(new FileOutputStream(file), BUF_SIZE);

            byte[] buffer = new byte[BUF_SIZE];
            int len;
            //写入文件
            while ((len = inputStream.read(buffer)) > 0) {
                out.write(buffer, 0, len);
            }
        } catch (IOException e) {
            throw new BusinessException("保存文件失败", e);
        } finally {
            //关闭输入输出流
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error("关闭文件输入流失败", e);
                }
            }
            if (null != out) {
                try {
                    out.close();
                } catch (IOException e) {
                    log.error("关闭文件输出流失败", e);
                }
            }
        }
    }



    /**
     * 为图片添加图片水印
     * @param source 原图
     * @param watermarkUrl 水印图片
     * @param output 制作完成的图片
     * @return true 添加成功 false 添加失败
     */
    public static Boolean markImgMark(String source, String watermarkUrl, String output)  {
        File file = new File(source);
        if(!file.exists()){
            throw new BusinessException("原图不存在：{}", source);
        }
        Image img;
        try {
            img = ImageIO.read(file);
        } catch (IOException e) {
            throw new BusinessException("文件读取失败，{}", file.getAbsolutePath(), e);
        }
        //原图宽度
        int width = img.getWidth(null);
        //原图高度
        int height = img.getHeight(null);
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        // 1、得到画笔对象
        Graphics2D g = bi.createGraphics();
        // 2、设置对线段的锯齿状边缘处理
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.drawImage(img.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);
        // 4、水印图片的路径 水印图片一般为gif或者png的，这样可设置透明度
        ImageIcon imgIcon = new ImageIcon(watermarkUrl);
        // 5、得到Image对象。
        Image con = imgIcon.getImage();
        int watermarkWidth = con.getWidth(null) ;
        int watermarkHeight = con.getHeight(null);

//        int iMarkHeight = (int)(height * WATERMARK_RATIO);
//        int iMarkWidth = (int) (((double)watermarkWidth / (double) watermarkHeight) * iMarkHeight);

        int iMarkWidth = (int)(width * WATERMARK_RATIO);
        int iMarkHeight = (int) (((double)watermarkHeight / (double) watermarkWidth) * iMarkWidth);


        //x轴间距
        int xSpace = (width - 2 * iMarkWidth - X_WATERMARK_NUM * iMarkWidth) / (X_WATERMARK_NUM - 1);
        //y轴间距
        int ySpace = (height - Y_WATERMARK_NUM * iMarkHeight) / (X_WATERMARK_NUM - 1);


        for (int x = 0; x < X_WATERMARK_NUM; x++){
            for (int y = 0; y < Y_WATERMARK_NUM; y++){
                int xPosition = iMarkWidth + x * (iMarkWidth + xSpace);
                int yPosition = y * (iMarkHeight + ySpace);
                g.drawImage(con, xPosition, yPosition, iMarkWidth, iMarkHeight, null);
            }
        }

        //正中间再放置一个水印
        g.drawImage(con, (width-iMarkWidth)/2, (height - iMarkHeight)/2, iMarkWidth, iMarkHeight, null);

        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
        g.dispose();
        File sf = new File(output);
        // 保存图片
        try {
            ImageIO.write(bi, "jpg", sf);
        } catch (IOException e) {
            throw new BusinessException("保存水印图片失败, {}", sf.getAbsolutePath(), e);
        }

        return true;
    }

    public static File getFileFromurl(String fileUrl, String filePathName){
        InputStream inStream = null;
        FileOutputStream outStream = null;

        try {
            //new一个URL对象
            URL url = new URL(fileUrl);
            //打开链接
            HttpURLConnection conn = (HttpURLConnection)url.openConnection();
            //设置请求方式为"GET"
            conn.setRequestMethod("GET");
            //超时响应时间为5秒
            conn.setConnectTimeout(5 * 1000);
            //通过输入流获取图片数据
            inStream = conn.getInputStream();
            //new一个文件对象用来保存图片，默认保存当前工程根目录
            File file = new File(filePathName);
            //文件输出流
            outStream = new FileOutputStream(file);
            //输出文件
            byte[] buff = new byte[4096];
            int len;
            while ((len = inStream.read(buff)) != -1) {
                outStream.write(buff,0,len);
            }

            return file;

        }catch (Exception e){
            throw new BusinessException("读取网络文件失败", e);
        }finally {
            if(outStream != null){
                try {
                    inStream.close();
                    outStream.close();
                } catch (IOException e) {
                    log.error("关闭输出流失败", e);
                }
            }
        }
    }
}
